package com.shiwaixiangcun.authz.shiro.realm;

import com.shiwaixiangcun.authz.service.AccountService;
import com.shiwaixiangcun.authz.shiro.authc.OAuth2UsernamePasswordToken;
import com.shiwaixiangcun.core.shiro.exception.AccountBlockedException;
import com.shiwaixiangcun.core.shiro.exception.AccountNotExistsException;
import com.shiwaixiangcun.core.shiro.exception.AccountPasswordNotMatchException;
import com.shiwaixiangcun.core.shiro.exception.AccountScopeException;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * Created by SilentWu on 2017/2/27.
 */
public class AccountRealm extends AuthorizingRealm {

    private static final Logger logger = LoggerFactory.getLogger(AccountRealm.class);

    @Autowired
    private AccountService accountService;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof OAuth2UsernamePasswordToken;// 表示此Realm只支持UsernamePasswordToken类型
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        OAuth2UsernamePasswordToken upToken = (OAuth2UsernamePasswordToken) token;
        String accountStr = upToken.getUsername().trim();
        String password = "";
        if (upToken.getPassword() != null) {
            password = new String(upToken.getPassword());
        }

        com.shiwaixiangcun.core.domain.account.Account account;
        try {
            account = accountService.login(accountStr, password, upToken.getScopes());
        } catch (AccountNotExistsException e) {
            throw new UnknownAccountException(e.getMessage(), e);
        } catch (AccountPasswordNotMatchException | AccountScopeException e) {
            throw new AuthenticationException(e.getMessage(), e);
        } catch (AccountBlockedException e) {
            throw new LockedAccountException(e.getMessage(), e);
        } catch (Exception e) {
            logger.error("login error", e);
            throw new AuthenticationException(new AccountException("未知错误"));
        }

        return new SimpleAuthenticationInfo(account, password.toCharArray(), getName());
    }


}
